/*
 * LowPass.cpp
 *
 *  Created on: Dec 4, 2009
 */

#include "LowPass.h"
#include <cmath>
#include <mpi.h>

LowPass::LowPass() {
}

LowPass::~LowPass() {
}

void LowPass::applyFilterInVector(int width, int height, int **vectors, int **newVectors) {
	if (vectors != NULL && newVectors != NULL) {
		int rank;
		MPI_Comm_rank ( MPI_COMM_WORLD, & rank);

		int proccess;
		MPI_Comm_size( MPI_COMM_WORLD, & proccess);

		int qtd = 0;
		int rest = 0;
		int max = qtd;

		qtd = height / proccess;
		rest = height % proccess;
		max = qtd * (rank + 1);

		if (rank == 0) {
			qtd += rest;
			max += rest;
		}


		int sendVector[qtd][width];
		int iRank = 0;

		for (int i = rank * qtd; i < max; i++) {
			#pragma omp parallel for default(shared)
			for (int j = 0; j < width; j++) {
				double calculatedValue = vectors[i][j];

				calculatedValue += getUpLeftValue(i, j, width, height, vectors);
				calculatedValue += getUpCenterValue(i, j, width, height, vectors);
				calculatedValue += getUpRightValue(i, j, width, height, vectors);
				calculatedValue += getCenterLeftValue(i, j, width, height, vectors);
				calculatedValue += getCenterRightValue(i, j, width, height, vectors);
				calculatedValue += getDownLeftValue(i, j, width, height, vectors);
				calculatedValue += getDownCenterValue(i, j, width, height, vectors);
				calculatedValue += getDownRightValue(i, j, width, height, vectors);

				calculatedValue /= 9;

				if (rank == 0) {
					newVectors[i][j] = (int) round(calculatedValue);
				} else {
					sendVector[iRank][j] = (int) round(calculatedValue);

				}
			}
			iRank++;
		}

		if (rank != 0) {
			MPI_Send(sendVector, qtd*width, MPI_INT, 0, 1, MPI_COMM_WORLD);
		}

		if (rank == 0) {
			for (int i = 1; i < proccess; i ++) {
				int recvVector[qtd][width];
				MPI_Status status;

				MPI_Recv(recvVector, qtd*width, MPI_INT, i, 1, MPI_COMM_WORLD, &status);

				int index = i * qtd;

				for (int line = 0; line < qtd; line++) {
					for (int column = 0; column < width; column++) {
						newVectors[index][column] = recvVector[line][column];
					}

					index++;
				}

				int ok = 1;
				MPI_Send(&ok, 1, MPI_INT, i, 1, MPI_COMM_WORLD);
			}
		} else {
			int isOk;
			MPI_Status status;
			MPI_Recv(&isOk, 1, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
		}
	}
}
